package cn.acewill.lrz.lambda;

import com.google.common.collect.Lists;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream测试
 * Stream 不是集合元素，它不是数据结构并不保存数据，它是有关算法和计算的，它更像一个高级版本的 Iterator。简单来说，它的作用就是通过一系列操作将数据源（集合、数组）转化为想要的结果。
 * Stream特点
 *    1、Stream 是不会存储元素的。
 *    2、Stream 不会改变原对象，相反，他们会返回一个持有结果的新Stream。
 *    3、Stream 操作是延迟执行的。意味着它们会等到需要结果的时候才执行。
 *
 */
public class StreamTest {
    public static void main(String arg[]) {
        StreamTest st = new StreamTest();

        /**
         * 生成Stream
         */
//        st.generatorStream();

        /**
         * 终止操作测试
         */
//        st.stopOption();

        /**
         * reduce （归约）：将流中元素反复结合起来得到一个值
         */
//        st.reduce();

        /*
         * collect（收集）：将流转换为其他形式。需要Collectors类的一些方法。
         */
        st.collect();

    }

    /**
     * collect（收集）：将流转换为其他形式。需要Collectors类的一些方法。
     */
    private void collect() {
        List<Integer> list = new ArrayList<Integer>(){{add(1);add(2);}};
        list = Lists.newArrayList();
        String[] intArr = new String[30];
        for(int i=0;i<30;i++) {
            Integer integer = Integer.valueOf("" + Math.round(Math.random()*10));
            intArr[i] = integer + "";
            System.out.print(integer + " ");
            list.add(integer);
        }
        System.out.println();
        List<String> arrayToList = Arrays.stream(intArr).collect(Collectors.toList());
        System.out.println("arrayToList===>"+arrayToList.toString());

        //转集合
        Set<Integer> collect = list.stream().collect(Collectors.toSet());

        List<Integer> collect2 = list.stream().collect(Collectors.toList());

        HashSet<Integer> collect1 = list.stream().collect(Collectors.toCollection(HashSet::new));

        //分组 {group=[444, 555, 666, 777, 555]}
        Map<String, List<Integer>> collect3 = list.stream().collect(Collectors.groupingBy((x) -> (""+x+1)));//将返回值相同的进行分组
        System.out.println();
        System.out.println(collect3);

        //多级分组 {group={777=[777], 666=[666], 555=[555, 555], 444=[444]}}
        Map<String, Map<Integer, List<Integer>>> collect4 = list.stream().collect(Collectors.groupingBy((x) -> (x<4?"3":x<7?"6":"10"), Collectors.groupingBy((x) -> x)));
        System.out.println(collect4);

        //分区 {false=[444], true=[555, 666, 777, 555]}
        Map<Boolean, List<Integer>> collect5 = list.stream().collect(Collectors.partitioningBy((x) -> x > 6));
        System.out.println(collect5);

        //汇总
        DoubleSummaryStatistics collect6 = list.stream().collect(Collectors.summarizingDouble((x) -> x));
        System.out.println(collect6.getMax());
        System.out.println(collect6.getCount());

        //拼接 444,555,666,777,555
        String collect7 = list.stream().map(s -> s.toString()).collect(Collectors.joining(","));
        System.out.println(collect7);

        //最大值
        Optional<Integer> integer = list.stream().collect(Collectors.maxBy(Integer::compare));
        System.out.println(integer.get());

//        List<acewill.lrz.Mode.Persion> persionList = Lists.newArrayList();
//        Random random = new Random();
//        for(int i=1;i<10;i++) {
//            acewill.lrz.Mode.Persion p = new acewill.lrz.Mode.Persion();
//            persionList.add(p);
//            p.setId(random.nextInt()+""+i);
//            p.setName("李"+i);
//            p.setAge(20+i);
//        }
//        Map<String, acewill.lrz.Mode.Persion> map = persionList.stream().collect(Collectors.toMap(acewill.lrz.Mode.Persion::getId, p->p));
//        for (Map.Entry<String, acewill.lrz.Mode.Persion> entry : map.entrySet()) {
//            System.out.println(entry.getKey() + ":" + entry.getValue().toString());
//        }
    }

    /**
     * reduce （归约）：将流中元素反复结合起来得到一个值
     */
    private void reduce() {
        List<Double> list = Lists.newArrayList();
        for(int i=0;i<30;i++) {
            list.add(Math.random()*100);
        }
        System.out.println(list.toString());
        Double oreduce = list.stream().reduce(0d, (x,y)->x+y);
        System.out.println(oreduce);
        Double reduce = list.stream().map(s -> (s + 1)).reduce(0d, (x,y)->x+y);
        //归约：0为第一个参数x的默认值，x是计算后的返回值，y为每一项的值。
        System.out.println(reduce);
        Optional<Double> reduce1 = list.stream().map(s -> (s + 1)).reduce((x, y) -> x + y);
        // x是计算后的返回值，默认为第一项的值，y为其后每一项的值。
        System.out.println(reduce1.get());
    }

    /**
     * 终止操作测试
     */
    private void stopOption() {
        List<Double> list = Lists.newArrayList();
        for(int i=0;i<30;i++) {
            list.add(Math.random()*100);
        }
        list.stream().allMatch(x->x<100); // 检查是否匹配所有元素
        list.stream().anyMatch(((x) -> x>50)); // 检查是否至少匹配一个元素
        list.stream().noneMatch((x) -> x>0); //检查是否没有匹配所有元素
        list.stream().findFirst(); // 返回第一个元素
        list.stream().findAny(); // 返回当前流中的任意一个元素
        list.stream().count(); // 返回流中元素的总个数
        list.stream().forEach(System.out::println); //内部迭代
        StringBuffer lists = new StringBuffer();
        list.stream().forEach(d -> lists.append(d+"").append(","));
        System.out.println("lists="+lists);
        Optional<Double> max = list.stream().max(Double::compareTo); // 返回流中最大值
        System.out.println("max "+max.get());
        Optional<Double> min = list.stream().min(Double::compareTo);//返回流中最小值
        System.out.println("min "+min.get());

        Map<String, Object> params = new TreeMap<>();
        params.put("app", "123");
        params.put("shopIdenty", "456");
        params.put("appKey", "123");
        params.put("timestamp", "101112");
        params.put("version", "789");
        StringBuilder sortedParams = new StringBuilder();
        params.entrySet().stream().forEachOrdered(paramEntry -> sortedParams.append(paramEntry.getKey()).append(paramEntry.getValue()));
        sortedParams.append("1456");
        System.out.println(sortedParams);
    }

    /**
     * 生成Stream
     */
    private void generatorStream() {
        //1、通过list生成
        System.out.println("----通过list生成测试START----");
        List<String> lists = Lists.newArrayList();
        lists.add("1");lists.add("3");lists.add("2");
        Stream<String> stream = lists.stream();
        stream.forEach(System.out::println);
        Stream<String> parallelStream = lists.parallelStream();
        parallelStream.forEach(System.out::println);
        System.out.println("----通过list生成测试END----");
        //2、通过Arrays生成
        System.out.println("----通过Arrays生成测试START----");
        Stream<String> arraysStream = Arrays.stream(new String[]{"4","1","3","2"});
        arraysStream.forEach(System.out::println);
        System.out.println("----通过Arrays生成测试END----");
        //3、生成
        System.out.println("----生成测试START----");
        Stream<Double> generate = Stream.generate(()->Math.random());
        generate.limit(10).forEach(System.out::println);
        System.out.println("----生成测试END----");
        //4、无限流迭代
        System.out.println("----无限流迭代测试START----");
        Stream<Integer> iteratorStream = Stream.iterate((0),x->x+2);
        iteratorStream.limit(10).forEach(System.out::println);
        System.out.println("----无限流迭代测试END----");
    }
}
